package com.dp.pub;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;
/*
 * Provides the the ability to use simple XML property files. Each property is
 * in the form X.Y.Z, which would map to an XML snippet of:
 * <pre>
 * &lt;X&gt;
 *     &lt;Y&gt;
 *         &lt;Z&gt;someValue&lt;/Z&gt;
 *     &lt;/Y&gt;
 * &lt;/X&gt;
 * </pre>
 *
 * The XML file is passed in to the constructor and must be readable and
 * writtable. Setting property values will automatically persist those value
 * to disk.
 */
public class xmlrw {

  private File file=null;
  private Document doc;
  /*
   * Parsing the XML file every time we need a property is slow. Therefore,
   * we use a Map to cache property values that are accessed more than once.
   */
  private Map propertyCache = new HashMap();

  /*
   * Creates a new XMLProperties object.
   *
   * @param file the full path the file that properties should be read from
   *      and written to.
   */
   
    /**
     * ���๹�췽��
     * @throws Exception    
     */    
   
  public xmlrw(String file) 
  {
    this.file = new File(file);
    try 
    {
       SAXBuilder builder = new SAXBuilder();
//       DataUnformatFilter format = new DataUnformatFilter();
//       builder.setXMLFilter(format);
       doc = builder.build(new File(file));
       //doc=builder.
    }
    catch (Exception e) {      e.printStackTrace();  }
  }
  public xmlrw() 
  {
	  doc=new Document();
	 // doc.
	  Element e=new Element("root");
	 // e.setAttribute("color","red").setText("tt");
	 // e.setAttribute("color1","red").setText("rtyrty");
	 // e.getChildren().add(new Element("root"));
	 // e.addContent(new Element("ni").setText("   ggg  ").setName("kkk"));
	  //d.setRootElement(new Element("root"));
	  //doc.addContent(e);
	  doc.setRootElement(e);
	
	  //doc.
	  
	 
	  //System.out.println(e.getAttribute("color").getAttributeType());
 
  }
  /*
   * Returns the value of the specified property.
   *
   * @param name the name of the property to get.
   * @return the value of the specified property.
   */
  /**
   * �ض��ֶ�ֵ��ȡ��ֵ
   */   
    class myException extends Exception
   {
        public myException() {
          }
          public myException(String message) {
            super(message);
          }
          public myException(Throwable throwable) {
            super(throwable);
          }
          public myException(String message, Throwable throwable) {
            super(message, throwable);
          }
   }   
  public String gettext(String name) 
  {
    if (propertyCache.containsKey(name)) { return (String) propertyCache.get(name);}
    String[] propName =parsePropertyName(name);    
    Element element = doc.getRootElement();
    for (int i = 0; i < propName.length; i++) 
    {
      element = element.getChild(propName[i]);
      if (element == null) { return null;}
    }
    String value = element.getText();
      value = value.trim();
      propertyCache.put(name, value);
      return value;

  }

  /*
   * Return all children property names of a parent property as a String array,
   * or an empty array if the if there are no children. For example, given
   * the properties <tt>X.Y.A</tt>, <tt>X.Y.B</tt>, and <tt>X.Y.C</tt>, then
   * the child properties of <tt>X.Y</tt> are <tt>A</tt>, <tt>B</tt>, and
   * <tt>C</tt>.
   *
   * @param parent the name of the parent property.
   * @return all child property values for the given parent.
   */
  /**
   * ����ض��ֶε����ֶ�����
   */      
  public String[] getChildrenProperties(String parent) {
    String[] propName = parsePropertyName(parent);
    Element element = doc.getRootElement();
    for (int i = 0; i < propName.length; i++) 
    {
      element = element.getChild(propName[i]);
      if (element == null) { return null; }
    }
   
    List children = element.getChildren();
    int childCount = children.size();
    String[] childrenNames = new String[childCount];
    for (int i = 0; i < childCount; i++)
    {
      childrenNames[i] = ( (Element) children.get(i)).getName();
    }
    return childrenNames;
  }

  /*
   * Sets the value of the specified property. If the property doesn't
   * currently exist, it will be automatically created.
   *
   * @param name the name of the property to set.
   * @param value the new value for the property.
   */
   
  /**
   * �ض��ֶ�ֵ�ĸ�ֵ
   */    
  public void setProperty(String name, String value) {
    propertyCache.put(name, value);

    String[] propName = parsePropertyName(name);
    // Search for this property by traversing down the XML heirarchy.
    Element element = doc.getRootElement();
    for (int i = 0; i < propName.length; i++) 
    {
      if (element.getChild(propName[i]) == null) {
        element.addContent(new Element(propName[i]));
      }
      element = element.getChild(propName[i]);
    }
   
    element.setText(value);
  }

  /*
   * Deletes the specified property.
   *
   * @param name the property to delete.
   */
  /**
   * ɾ���ض��ֶ� 
   */      
  public void deleteProperty(String name) 
  {
    String[] propName = parsePropertyName(name);
    Element element = doc.getRootElement();
    for (int i = 0; i < propName.length - 1; i++) 
    {
      element = element.getChild(propName[i]);
      if (element == null) { return;}
    }
    element.removeChild(propName[propName.length - 1]);   
  }

  /*
   * Saves the properties to disk as an XML document. A temporary file is
   * used during the writing process for maximum safety.
   */
     /**
   * �����Դ浽xml�ĵ�
   */  
  public void saveAs(String filename)
  {
  	OutputStream out = null;
    File tempFile = null;
    try {
     // tempFile = new File(filename );
    	if (file!=null)
    		tempFile =  new File(file.getParentFile(), filename);
    	else
    	{
    		//this.getClass().�½�bҪ��·��
    		tempFile =  new File(file.getParentFile(), filename);
    	}
      XMLOutputter outputter = new XMLOutputter();
	  Format fo=Format.getRawFormat();
		
		  fo.setIndent("  ");
		  fo.setOmitEncoding(false);
		  fo.setEncoding("GB2312");
		  fo.setTextMode(Format.TextMode.TRIM);
		  fo.setExpandEmptyElements(true);
		  //System.out.println(fo.getLineSeparator());
		  //outputter.output(d.getRootElement(),System.out);
      out = new BufferedOutputStream(new FileOutputStream(tempFile));
      outputter.setFormat(fo);
      outputter.output(doc, out);
    }
    catch (Exception e) {      e.printStackTrace();}
    finally 
    {      try {        out.close();      }
           catch (Exception e) {      e.printStackTrace();}
    }
  	
  	
  	
  }
  public void print(PrintWriter pw)
  {
	  try{ XMLOutputter op=new XMLOutputter();
	   Format fo=Format.getRawFormat();	
		  //fo.setIndent("  ");
		  //fo.setOmitEncoding(false);
		  //fo.setEncoding("GB2312");
	   fo.setEncoding("utf-8");
		 // fo.setTextMode(Format.TextMode.TRIM);
		 // fo.setExpandEmptyElements(true);
		  op.setFormat(fo);
	     op.output(doc,pw); /**/
	     
	 } catch (Exception e) {      e.printStackTrace();}
  }
  public void print(OutputStream out)
  {
	 try{ XMLOutputter op=new XMLOutputter();
	   Format fo=Format.getRawFormat();	
		 // fo.setIndent("  ");
		 // fo.setOmitEncoding(false);
		  fo.setEncoding("GB2312");
		 // fo.setTextMode(Format.TextMode.TRIM);
		 // fo.setExpandEmptyElements(true);
		  op.setFormat(fo);
	     op.output(doc,out); /**/
	 } catch (Exception e) {      e.printStackTrace();}
	    
  }
//  private synchronized void saveProperties() {
//    OutputStream out = null;
//    boolean error = false;
//    // Write data out to a temporary file first.
//    File tempFile = null;
//    try {
//      tempFile = new File(file.getParentFile(), file.getName() + ".tmp");
//      // Use JDOM's XMLOutputter to do the writing and formatting. The
//      // file should always come out pretty-printed.
//      XMLOutputter outputter = new XMLOutputter("    ", true);
//      out = new BufferedOutputStream(new FileOutputStream(tempFile));
//      outputter.output(doc, out);
//    }
//    catch (Exception e) {
//      e.printStackTrace();
//      // There were errors so abort replacing the old property file.
//      error = true;
//    }
//    finally {
//      try {
//        out.close();
//      }
//      catch (Exception e) {
//        e.printStackTrace();
//        error = true;
//      }
//    }
//    // No errors occured, so we should be safe in replacing the old
//    if (!error) {
//      // Delete the old file so we can replace it.
//      //file.delete();
//      // Rename the temp file. The delete and rename won't be an
//      // automic operation, but we should be pretty safe in general.
//      // At the very least, the temp file should remain in some form.
//      //tempFile.renameTo(file);
//    }
//  }

   public Document getDocument()
   {
       return doc;	
   }
   private String[] parsePropertyName(String name) 
  {
    if(name==null) return null;
    String []propName =name.split("[.]");
    for(int i=0;i<propName.length ;i++)  if(propName[i].equals("")) return null;    
    return propName;
  }
}